<?php
/**
 * 对数组嵌套类型的值一次性检查是否重复
 *
 * @author Zeon <scplay@gmail.com>
 * @date 2018/6/14
 * @copyright PanxSoft Inc.
 */
namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

/**
 * Class ArrayUnique
 *
 * @test
 * @see \Tests\Misc\Requests\GeneralRequestTest::test_request_rule_array_unique_query_time()
 *
 * @package App\Rules
 */
class ArrayUnique implements Rule
{
    private $all_data = [];

    private $checked = false;

    protected $duplicate_vals = [];
    /**
     * @var bool
     */
    private $validate_null;

    /**
     * Create a new rule instance.
     *
     * @param array $all_data
     * @param bool $validate_null
     */
    public function __construct(array $all_data, $validate_null = false)
    {
        $this->all_data = $all_data;
        $this->validate_null = $validate_null;
    }

    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        if ($this->checked) {
            return true;
        }

        $asterisk_attr = $this->replaceIndexToAsterisks($attribute);

        $validate_vals = data_get($this->all_data, $asterisk_attr);

        // do not check null or empty string
        if (! $this->validate_null) {
            $validate_vals = array_filter($validate_vals);
        }

        $pass = count($this->duplicate_vals) === count(array_unique($validate_vals));

        $this->duplicate_vals = $validate_vals;

        $this->checked = true;

        return $pass;
    }

    /**
     * @example  'dev.12.uuid.3' => 'dev.*.uuid.*'
     *
     * @param $attr
     *
     * @return null|string|string[]
     */
    private function replaceIndexToAsterisks($attr)
    {
        return preg_replace('/\.\d+/', '.*', $attr);
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        $duplicate_val_str = implode(',', $this->duplicate_vals);

        return "There are duplicated values in array {$duplicate_val_str}.";
    }
}
